/*
 * File: HangmanCanvas.java
 * ------------------------
 * This file keeps track of the Hangman display.
 */

import acm.graphics.*;

public class HangmanCanvas extends GCanvas {

	private int incorrectGuesses = 0;
	
/** Resets the display so that only the scaffold appears */
	public void reset() {
		removeAll();
		
		drawScaffold();
		
		incorrectGuesses = 0;
	}
	
	/**
	 * Gets the initial position of the scaffold
	 * @return
	 */
	private GPoint getScaffoldXY(){
		double x = getWidth()/2/2;
		double y = getHeight()/2 - BODY_LENGTH - HEAD_RADIUS * 2 - ROPE_LENGTH;
		
		return new GPoint(x, y);
	}
	
	public void drawScaffold(){
		GPoint scaffoldXY = getScaffoldXY();
		
		GLine scaffold= new GLine (scaffoldXY.getX(), scaffoldXY.getY(), scaffoldXY.getX(), scaffoldXY.getY() + SCAFFOLD_HEIGHT);
		add(scaffold);
		
		double beamLength = scaffoldXY.getX() + BEAM_LENGTH;
		GLine beam = new GLine(scaffoldXY.getX(), scaffoldXY.getY(), beamLength, scaffoldXY.getY());
		add(beam);
		
		GLine rope = new GLine(beamLength, scaffoldXY.getY(), beamLength, scaffoldXY.getY() + ROPE_LENGTH);
		add(rope);
	}
/**
 * Updates the word on the screen to correspond to the current
 * state of the game.  The argument string shows what letters have
 * been guessed so far; unguessed letters are indicated by hyphens.
 */
	public void displayWord(String word) {
		addWordLabel(word);
	}
	
	private void addWordLabel(String word){
		double wordX = getWidth()/4;
		double wordY = getHeight() - ROPE_LENGTH * 3;
		
		Object objectAtXY = getElementAt(wordX, wordY);
		
		GLabel label = null;
		if (objectAtXY==null){
			label = new GLabel(word, wordX, wordY);
			label.setFont("Arial-24");
			add(label);
		}
		else{
			label = (GLabel)objectAtXY;
			label.setLabel(word);
		}		
	}
	
	/**
	 * Gets the screen label of incorrect letters
	 * @return
	 */
	private GLabel getCurrentIncorrectLettersLabel(){ 
		double incorrectLetterX = getWidth()/4; 
		double incorrectLetterY = getHeight() - ROPE_LENGTH * 2;
		
		GObject objectAtXY = getElementAt(incorrectLetterX, incorrectLetterY);
		if (objectAtXY==null){
			objectAtXY = new GLabel("", incorrectLetterX, incorrectLetterY);
			add(objectAtXY);
		}
		
		return (GLabel)objectAtXY;		
	}
/**
 * Updates the display to correspond to an incorrect guess by the
 * user.  Calling this method causes the next body part to appear
 * on the scaffold and adds the letter to the list of incorrect
 * guesses that appears at the bottom of the window.
 */
	public void noteIncorrectGuess(char letter) {
		GLabel currentIncorrectLetters = getCurrentIncorrectLettersLabel();
		currentIncorrectLetters.setLabel(currentIncorrectLetters.getLabel() + letter);
		
		incorrectGuesses++;
		
		updateHangman(incorrectGuesses);
	}
	
	/**
	 * Updates hangman graph according the number of incorrectGuesses
	 * @param incorrectGuesses
	 */
	private void updateHangman(int incorrectGuesses){
		if (incorrectGuesses==1){
			drawHead();
		}
		if (incorrectGuesses==2){
			drawBody();
		}
		if (incorrectGuesses==3){
			drawLeftArm();
		}
		if (incorrectGuesses==4){
			drawRightArm();
		}
		if (incorrectGuesses==5){
			drawLeftLeg();
		}
		if (incorrectGuesses==6){
			drawRightLeg();
		}
		if (incorrectGuesses==7){
			drawLeftFoot();
		}
		if (incorrectGuesses==8){
			drawRightFoot();
		}
	}
	
	private void drawHead(){
		double headX = getWidth()/2  - HEAD_RADIUS/2;
		double headY = getHeight()/2 - BODY_LENGTH - HEAD_RADIUS*2;
		GOval head = new GOval(headX, headY, HEAD_RADIUS, HEAD_RADIUS);
		add(head);
	}
	
	private void drawBody(){
		double bodyX = getWidth()/2;
		double bodyStartY = getHeight()/2 - BODY_LENGTH - HEAD_RADIUS;
		double bodyEndY = getHeight()/2;
		
		GLine body = new GLine(bodyX, bodyStartY, bodyX, bodyEndY);
		add(body);
	}
	
	private void drawLeftArm(){
		double armStartX = (getWidth() / 2) -  UPPER_ARM_LENGTH/2;
		double armEndX = (getWidth() / 2);
		double armStartY = (getHeight() / 2) - BODY_LENGTH - HEAD_RADIUS/2 + ARM_OFFSET_FROM_HEAD;
		
		GLine arm = new GLine(armStartX, armStartY, armEndX, armStartY);
		add(arm);
		GLine foreArm = new GLine(armStartX, armStartY, armStartX, armStartY + LOWER_ARM_LENGTH/2);  
		add(foreArm);
	} 
	
	private void drawRightArm(){
		double armStartX = (getWidth() / 2) + UPPER_ARM_LENGTH/2;
		double armEndX = (getWidth() / 2);
		double armStartY = (getHeight() / 2) - BODY_LENGTH - HEAD_RADIUS/2 + ARM_OFFSET_FROM_HEAD;
		
		GLine arm = new GLine(armStartX, armStartY, armEndX, armStartY);
		add(arm);
		GLine foreArm = new GLine(armStartX, armStartY, armStartX, armStartY + LOWER_ARM_LENGTH/2);  
		add(foreArm);
	}
	
	private void drawLeftLeg(){
		double hipStartX = (getWidth() / 2) - HIP_WIDTH / 2;
		double hipEndX = (getWidth() / 2);
		double hipStartY = (getHeight() / 2);
		
		GLine hip = new GLine(hipStartX, hipStartY, hipEndX, hipStartY);
		add(hip);
		
		GLine leg = new GLine(hipStartX, hipStartY, hipStartX, hipStartY + LEG_LENGTH/2);
		add(leg);
	}
	
	private void drawRightLeg(){
		double hipStartX = (getWidth() / 2) + HIP_WIDTH / 2;
		double hipEndX = (getWidth() / 2);
		double hipStartY = (getHeight() / 2);
		
		GLine hip = new GLine(hipStartX, hipStartY, hipEndX, hipStartY);
		add(hip);
		
		GLine leg = new GLine(hipStartX, hipStartY, hipStartX, hipStartY + LEG_LENGTH/2);
		add(leg);
	}
	
	private void drawLeftFoot(){
		double footEndX = (getWidth() / 2) - HIP_WIDTH / 2;
		double footStartX = footEndX - FOOT_LENGTH/2;
		double footStartY = (getHeight() / 2) + LEG_LENGTH/2;
		
		GLine foot = new GLine(footStartX, footStartY, footEndX, footStartY);
		add(foot);
	}
	
	private void drawRightFoot(){
		double footEndX = (getWidth() / 2) + HIP_WIDTH / 2;
		double footStartX = footEndX + FOOT_LENGTH/2;
		double footStartY = (getHeight() / 2) + LEG_LENGTH/2;
		
		GLine foot = new GLine(footStartX, footStartY, footEndX, footStartY);
		add(foot);
	}
	
/* Constants for the simple version of the picture (in pixels) */
	private static final int SCAFFOLD_HEIGHT = 200;
	private static final int BEAM_LENGTH = 94;
	private static final int ROPE_LENGTH = 18;
	private static final int HEAD_RADIUS = 36;
	private static final int BODY_LENGTH = 50;
	private static final int ARM_OFFSET_FROM_HEAD = 0;
	private static final int UPPER_ARM_LENGTH = 72;
	private static final int LOWER_ARM_LENGTH = 44;
	private static final int HIP_WIDTH = 36;
	private static final int LEG_LENGTH = 108;
	private static final int FOOT_LENGTH = 28;

}
